package cli.menu;

import java.util.ArrayList;
import shared.*;
import cli.tools.Process;

//@author A0085686L
/*by LI YIN
 */
public class AddReceipt extends Function{
	private static final String[] selectmode = {
		"-= Main menu > Add Entry > Expense with Receipt =-",
		"[b]: back [u]: undo [r]: redo [h]: home menu",
		"Select a payment method: " 
	};
	private static final String[] selectcat = {
		"-= Main menu > Add Entry > Expense with Receipt =-",
		"[b]: back [u]: undo [r]: redo [h]: home menu",
		"Select a category: " 
	};
	private static final String[] inputReceipt = {
		"-= Main menu > Add Entry > Expense with Receipt =-",
		"[b]: back [u]: undo [r]: redo [h]: home menu",
		"",
		"Enter receipt information in the following format, remember to put a / even if you leave the optional field blank: ",
		"Name / Shop / Receipt Number / Total paid / Date (DD.MM.YYYY, optional) / Contact NO. (optional) / Description (optional)",
		"", 
		"Input: " 
	};
	private static final String[] inputItem = {
		"-= Main menu > Add Entry > Expense with Receipt =-",
		"[b]: back [u]: undo [r]: redo [h]: home menu",
		"",
		"Enter purchased items on receipt in the following format",
		"remember to put a / even if you leave the optional field blank: ",
		"Name / Price / Serial Number (optional) / Model (optional) / Brand (optional) / Description (optional)",
		"",
		"(Press Enter with no input to finish listing)",
		"Input: " 
	};
	
	private static final State back = State.ADDENTRYMENU;
	private static final State current = State.ADDRECEIPT;
	
	public static State runmenu(){
		
		cli.print(selectmode);
		
		Object choice = tools.selectFromList(cli.getApi().getModeList(), "Payment Mode");
		if(choice==null)
			return back;
		if(choice.getClass()==State.class)
			return (State) choice;
		Mode paymentMode = (Mode)choice;
		
		cli.print(selectcat);

		choice = tools.selectFromList(cli.getApi().getCategoryList(), "Category");
		// if choice is not null, it is a re-direction to another menu screen
		if (choice == null) {
			return back;
		}
		// if received Instruction object (divert to another menu)
		if (choice.getClass() == State.class) {
			return (State) choice;
		}
		// last case: category has been set
		Category category = (Category) choice;

		return inputReceipt(paymentMode, category);
	}
	
	// method to handle receiving input for receipt
	private static State inputReceipt(Mode paymentMode, Category category) {

		State nextState = current;

		String input;
		
		//loop to check input validity
		while (nextState==current) {
			cli.print(inputReceipt);
			input = cli.nextLine();
			// check if input is a hotkey
			if (input.length() == 1) {
				char charInput = input.charAt(0);
				if (tools.isHotKey(charInput)){
					return hotKeyFunction(charInput);
				}
			} else {
				nextState = processReceipt(input, paymentMode, category);
			}
		}
		return nextState;

	}

	// the boolean value indicates if there is a successful, error free entry
	private static State processReceipt(String input, Mode paymentMode, Category category) {

		// process user input
		String[] processing = input.split("/");

// checks if input is valid : at least 4 "attributes" - name, shop, receipt # and total paid
		if (processing.length < 4) {
			cli.print(INSUFFINFO);
			return current;
		}
		
		String 		name = processing[0];
		String 		shop = processing[1];
		String receiptNO = processing[2];
		String totalPaid = processing[3];
		String   contact = "";
		String   details = "";
			
// checks price for validity
		int amount = tools.Money2int(totalPaid);
		if (amount <= 0) {
			cli.print(BADAMT);
			return current;
		}

//check date validity. 
		int[] dmy = new int[3];
		//set default date to today
		dmy = tools.initDate();
		//if there's a valid date assign dmy to the input specified date
		if(processing.length>4 && !processing[4].equals("")){
			try {
				//no error: it is valid date
				dmy = tools.processDate(processing[4]);
			} catch (Exception e) {
				//error: not a valid date
				cli.print(INVALIDDATE);
			}
		}
//check whether there's a contact field
		if(processing.length>5 && !processing[5].equals("")){
			contact = processing[5];
		}
//put everything after 7th entry inclusive to details field
		if(processing.length>6){
			for (int i = 6; i < processing.length; i++)
				details += processing[i] + " ";
		}
		
		Receipt receipt;
		/**************************************************************************************/
		try {
			receipt = cli.getApi().addReceipt(name, amount, dmy[0],
					dmy[1], dmy[2], details, paymentMode, category, shop, receiptNO, contact);
			// Si Ling: **Keeping Track of the Actions DONE**
			tools.action.addToUndoStack(null, receipt, Process.ADDRECEIPT, null);
			// **END**
		} catch (Exception e) {
			cli.print(ERROR);
			return current;
		}
		/*****************************************************************************************/
		State nextState = inputReceiptItem(receipt);
		
		return nextState;
	}
	
	//as long as the string contains pure numbers and '-', it is treated as a phone number
/*	private static boolean processContact (String unknown) {
		if(Pattern.matches("[0-9+/. ()-]+", unknown))
			return true;
		return false;
	}*/
	
	private static State inputReceiptItem(Receipt receipt){
		int finished[]=new int[1];
		finished[0]=0;
		boolean inputValid = false;
		ArrayList<ReceiptItem> itemList=new ArrayList<ReceiptItem>();
		String input="";
		
		//loop to receive input
		while(finished[0]!=1){
			//loop to check input validity
			while (!inputValid) {
				cli.print(inputItem);
				input = cli.nextLine();
				// check if input is a hotkey
				if (input.length() == 1) {
					char charInput = input.charAt(0);
					if (tools.isHotKey(charInput)){
						return hotKeyFunction(charInput);
					}
				} else {
					inputValid = processReceiptItem(input, receipt, finished);
				}
			}
			inputValid=false;
		}
		
		//System.out.println("debug: "+name+"/"+amount+"/"+dd+"."+mm+"."+yy+"/"+shop+"/"+receiptNO+"/"+contact);
		for (int i=0; i<itemList.size();i++){
			itemList.get(i).toString();
		}
		
		return back;
	}
	
/*	private static void addReceipt(String name, int amount, int dd, int mm, int yy, String details, Mode paymentMode, 
			Category category, String shop, String receiptNO, String contact, ArrayList<ReceiptItem> itemList){
		
		try {
			Receipt receipt = cli.getApi().addReceipt(name, amount, dd,
					mm, yy, details, paymentMode, category, shop, receiptNO, contact);
			// Si Ling: **Keeping Track of the Actions DONE**
			tools.action.addToUndoStack(null, receipt, Process.ADDRECEIPT, null);
			// **END**
		} catch (Exception e) {
			cli.print(ERROR);
			return;
		}
		
	}*/
	
	private static boolean processReceiptItem(String input,Receipt receipt, int[] finished){
		
//check finishing condition
		if(input.equals("")){
			if (receipt.getItems().size()==0){
				System.out.println("receipt list must contain at least 1 entry");
				return false;
			}else{
				finished[0]=1;
				return true;
			}
		}
		
// process user input
		String[] processing = input.split("/");

// checks if input is valid : at least 2 "attributes" - item name and price
		if (processing.length < 2) {
			cli.print(INSUFFINFO);
			return false;
		}
		
		String 		name = processing[0];
		String 	   price = processing[1];
		String	  serial = "";
		String     model = "";
		String 	   brand = "";
		String	 details = "";

// checks price for validity
		int amount = tools.Money2int(price);
		if (amount <= 0) {
			cli.print(BADAMT);
			return false;
		}
		
//if valid, add entry
		
		//if has serial field
		if (processing.length > 2 && !processing[2].equals("")) {
			serial = processing[2];
		}
		//if has model type
		if (processing.length > 3 && !processing[3].equals("")) {
			model = processing[3];
		}
		//if has brand
		if (processing.length > 4 && !processing[4].equals("")) {
			brand = processing[4];
		}
		//if has detail
		if(processing.length > 5){
			details = processing[5];
		}
		cli.getApi().addReceiptItem(receipt, new ReceiptItem(name,amount,serial,model,brand,details,receipt));
		System.out.println("item added to list");
		System.out.println(receipt.getItems().get(receipt.getItems().size()-1));
		return true;
	}

	private static State hotKeyFunction(char charInput) {

		State nextState = current;

		switch (charInput) {
		case 'b':
		case 'B':
			nextState = back;
			break;
		case 'u':
		case 'U':
			tools.undo();
			break;
		case 'r':
		case 'R':
			tools.redo();
			break;
		case 'h':
		case 'H':
			nextState = State.MAINMENU;
			break;
		default:
			break;
		}

		return nextState;

	}
}

